/**
 * @author Tobias Boehm
 *
 * 26.05.2011
 */
package org.anddev.andengine.extension.tbsengine.server;

import java.io.IOException;

import org.anddev.andengine.extension.multiplayer.protocol.adt.message.Message;
import org.anddev.andengine.extension.multiplayer.protocol.adt.message.client.ClientMessage;
import org.anddev.andengine.extension.multiplayer.protocol.adt.message.client.IClientMessage;
import org.anddev.andengine.extension.multiplayer.protocol.adt.message.server.IServerMessage;
import org.anddev.andengine.extension.multiplayer.protocol.adt.message.server.ServerMessage;
import org.anddev.andengine.extension.multiplayer.protocol.client.IServerMessageHandler;
import org.anddev.andengine.extension.multiplayer.protocol.client.connector.ServerConnector;
import org.anddev.andengine.extension.multiplayer.protocol.server.IClientMessageHandler;
import org.anddev.andengine.extension.multiplayer.protocol.server.connector.ClientConnector;
import org.anddev.andengine.extension.multiplayer.protocol.shared.Connection;
import org.anddev.andengine.extension.tbsengine.message.ICopyable;

/**
 * This class solves a problem (described below) with {@link Message} objects 
 * by copying those objects and calling {@link #onHandleMessageCopy(ServerConnector, ServerMessage)}
 * with the copy. You can use this class instead of {@link IClientMessageHandler}.
 * <p>
 * The problem:<br>
 * The whole message handling system of AndEngine is memory optimized.
 * Somehow the current (14.06.2011 - AndEngine Multiplayer Extension)
 * implementation causes problems if many messages of the same type
 * arrive at the same time. In this case they (!) share
 * an instance of their class and may override their member variables.
 * 
 * @author Tobias Boehm
 *
 * @param <MessageTypeClass> A message class which extends {@link ClientMessage} and implements {@link ICopyable}.
 * @param <ConnectionTypeClass> A connection type (a class which extends {@link Connection}).
 */
public abstract class AbsClientMessageCopyHandler<MessageTypeClass extends ClientMessage & ICopyable<MessageTypeClass>,
											  			ConnectionTypeClass extends Connection> 

											   			implements IClientMessageHandler<ConnectionTypeClass> {
	
	/**
	 * This method handles the incoming message and creates a copy of it. Then 
	 * it calls {@link #onHandleMessageCopy(ClientConnector, ClientMessage)}
	 * 
	 * @param pClientConnector
	 * @param pClientMessage
	 */
	@Override
	public void onHandleMessage(final ClientConnector<ConnectionTypeClass> pClientConnector, IClientMessage pClientMessage) throws IOException {
		
		final MessageTypeClass sourceMessage = (MessageTypeClass) pClientMessage;
		
		this.onHandleMessageCopy(pClientConnector, sourceMessage.copy());
	}
	
	/**
	 * This method should handle the new message like the usual implementation 
	 * of {@link IServerMessageHandler#onHandleMessage(ServerConnector, IServerMessage)}. 
	 * 
	 * @param pClientConnector
	 * @param pMessage
	 */
	public abstract void onHandleMessageCopy(final ClientConnector<ConnectionTypeClass> pClientConnector, final MessageTypeClass pMessage);
}
